/**
 * @params diffs diff数组 必传
 * @params diffsSha1Map diff路径对象 必传 {[sha1('readme.md')]: 'readme.md'} key为路径sha1值,value: 路径
 * @params loading 是否正在加载数据
 * @params hash 当前激活的hash，location.hash
 * @params markFileAsRead 标记为已读
 * @params markFileAsUnRead 标记为未读
 * @params isShowReadMark 是否有标记已读未读功能(commits compare 是+-行数和已读未读，直接隐藏后面的额外信息)
 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Balloon, Loading } from '@teamix/ui';
import sha1 from 'sha1';
import { treeFromPaths } from './path-to-tree';
import { YunxiaoIcon } from '@alife/devops-ui';
import ListEmpty from 'atComponents/ListEmpty';
import ColorText from 'components/colorText';
import './tree.scss';
import intl from '../../locale';

export default class TreeComit extends Component {
  static propTypes = {
    diffs: PropTypes.array,
    diffsSha1Map: PropTypes.object,
    loading: PropTypes.bool,
    hash: PropTypes.object,
    markFileAsUnRead: PropTypes.func,
    markFileAsRead: PropTypes.func,
    isShowReadMark: PropTypes.bool,
    setHash: PropTypes.func,
    isNewCommitOnchange: PropTypes.bool,
  };

  static defaultProps = {
    diffs: [],
    diffsSha1Map: {},
    loading: false,
    hash: {},
    markFileAsUnRead: () => {},
    markFileAsRead: () => {},
    isShowReadMark: false,
    setHash: () => {},
  };

  constructor(props) {
    super(props);

    this.state = {
      searchText: '',
      collapseTreeItemArr: [],
    };
  }

  componentDidMount() {
    const hasAoneNoticeBar = document.querySelector('.has-aonel-notice');
    const aoneNavHeight = hasAoneNoticeBar ? 70 : 45;
    const viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
    const crTabsHeight = 42;
    const crTabsPaddingTop = 15;
    const $leftDom = document.querySelector('.changes-left');
    if ($leftDom) {
      $leftDom.style['max-height'] = `${
        viewportHeight - crTabsHeight - crTabsPaddingTop - aoneNavHeight
      }px`;
    }
  }

  toggleTreeCollapse = (path) => {
    const collapseTreeItemArr = [...this.state.collapseTreeItemArr];
    const index = collapseTreeItemArr.findIndex((item) => {
      return item === path;
    });
    if (index > -1) {
      collapseTreeItemArr.splice(index, 1);
    } else {
      collapseTreeItemArr.push(path);
    }
    this.setState({
      collapseTreeItemArr,
    });
  };

  treeLoop(treeData) {
    const { diffs, diffsSha1Map, hash, isShowReadMark } = this.props;
    const { file: activeFileSha } = hash;
    const activeFilePath = activeFileSha ? diffsSha1Map[activeFileSha] : diffs[0].new_path;

    if (!treeData.nodes.length) {
      return null;
    }

    return (
      <div>
        {treeData.nodes.map((item) => {
          const diffData = diffs.find((diff) => diff.new_path === item.label.path);
          const isCollapsed = this.state.collapseTreeItemArr.find((arrItem) => {
            return arrItem === item.label.name;
          });
          let iconJsx;
          if (item.label.isFile) {
            if (diffData.new_file) {
              iconJsx = (
                <YunxiaoIcon
                  size="small"
                  type="additive-code-file-line"
                  className="file-icon-add changes-tree-item-icon"
                />
              );
            } else if (diffData.deleted_file) {
              iconJsx = (
                <YunxiaoIcon
                  size="small"
                  type="deleted-code-file-line"
                  className="file-icon-delete changes-tree-item-icon"
                />
              );
            } else {
              iconJsx = (
                <YunxiaoIcon
                  size="small"
                  type="modified-code-file-line"
                  className="file-icon-modify changes-tree-item-icon"
                />
              );
            }
          }

          return (
            <div className="changes-tree-item">
              {item.label.isFile ? (
                <div className="changes-tree-item-file">
                  <a
                    id={`tree_${sha1(item.label.path)}`}
                    className={`changes-tree-item-file-name one-line-ellipsis text-black ${
                      activeFilePath === item.label.path ? 'active' : ''
                    }`}
                    onClick={() => {
                      this.props.setHash(sha1(item.label.path));
                    }}
                    href={`#anchor_file_${sha1(item.label.path)}`}
                  >
                    {iconJsx}
                    <ColorText name={item.label.name} filterText={this.state.searchText} />
                  </a>
                  {/* 只有MR中有这个信息，因为接口返回数据信息含有line 是否已读 */}
                  {isShowReadMark && !item.nodes.length ? (
                    <span className="changes-tree-item-right">
                      {diffData.add_lines ? (
                        <Balloon.Tooltip
                          trigger={
                            <span className="changes-tree-item-right-item add-lines">
                              +{diffData.add_lines}
                            </span>
                          }
                          align="t"
                        >
                          {intl.get(
                            {
                              id: 'code-assets.components.treeAndDiff.tree.AddedDiffdataaddlinesLines',
                              defaultMessage: '增加了{diffDataAddLines}行',
                            },
                            { diffDataAddLines: diffData.add_lines },
                          )}
                        </Balloon.Tooltip>
                      ) : null}
                      {diffData.del_lines ? (
                        <Balloon.Tooltip
                          trigger={
                            <span className="changes-tree-item-right-item del-lines">
                              -{diffData.del_lines}
                            </span>
                          }
                          align="t"
                        >
                          {intl.get(
                            {
                              id: 'code-assets.components.treeAndDiff.tree.DiffdatadellinesLinesHaveBeenDeleted',
                              defaultMessage: '删除了{diffDataDelLines}行',
                            },
                            { diffDataDelLines: diffData.del_lines },
                          )}
                        </Balloon.Tooltip>
                      ) : null}
                      {diffData.read ? (
                        <Balloon.Tooltip
                          trigger={
                            <YunxiaoIcon
                              className="changes-tree-item-right-item mark-read-btn-read"
                              type="true-line1"
                              size="small"
                              onClick={() => {
                                this.props.markFileAsUnRead(diffData.new_object_id);
                              }}
                            />
                          }
                          align="t"
                        >
                          {intl.get({
                            id: 'code-assets.components.treeAndDiff.tree.MarkAsUnread',
                            defaultMessage: '标记为未读',
                          })}
                        </Balloon.Tooltip>
                      ) : (
                        <Balloon.Tooltip
                          trigger={
                            <YunxiaoIcon
                              className="changes-tree-item-right-item mark-read-btn-unread"
                              type="a-ziyuan2"
                              size="small"
                              onClick={() => {
                                this.props.markFileAsRead(diffData.new_object_id);
                              }}
                            />
                          }
                          align="t"
                        >
                          {intl.get({
                            id: 'code-assets.components.treeAndDiff.tree.MarkAsRead',
                            defaultMessage: '标记为已读',
                          })}
                        </Balloon.Tooltip>
                      )}
                    </span>
                  ) : null}
                </div>
              ) : (
                <div>
                  <div
                    className="changes-tree-item-folder"
                    title={item.label.name}
                    onClick={() => {
                      this.toggleTreeCollapse(item.label.name);
                    }}
                  >
                    <YunxiaoIcon
                      type={`trilateral-${isCollapsed ? 'right' : 'down'}-fill`}
                      className="changes-tree-item-folder-toggle"
                      style={{ marginLeft: 12 }}
                    />
                    <YunxiaoIcon
                      type="folder-line"
                      className="changes-tree-item-icon"
                      style={{
                        fontSize: '14px',
                        marginLeft: '2px',
                        marginRight: '5px',
                        verticalAlign: 'text-bottom',
                      }}
                    />

                    {item.label.name}
                  </div>
                  {isCollapsed ? null : (
                    <div className="changes-tree-item-folder-children">{this.treeLoop(item)}</div>
                  )}
                </div>
              )}
            </div>
          );
        })}
      </div>
    );
  }

  // 之所以注释，是因为0223这一期的文件树形结构，不太符合预期，仍然沿用老版树形结构
  renderTree = (filteredDiffs, treeData, loading) => {
    const { isNewCommitOnchange } = this.props;
    // if (filteredDiffs.length && !isNewCommitOnchange) {
    //   return (
    //     <Tree
    //       defaultExpandAll
    //       dataSource={treeData}
    //       onSelect={this.onSelect}
    //       useVirtual
    //       style={{ height: `calc(100vh - ${this.props.commitTreeHeight}px )`, overflowY: 'auto' }}
    //     />
    //   );
    // } else
    if (filteredDiffs.length) {
      // && isNewCommitOnchange
      const style = isNewCommitOnchange ? { style: { marginLeft: -26 } } : {};
      return <div {...style}>{this.treeLoop(treeData)}</div>;
    } else if (loading) {
      return (
        <div className="diff-loading">
          <Loading visible style={{ height: '100px' }} />
        </div>
      );
    } else {
      return (
        <div className="no-data">
          <ListEmpty
            content={intl.get({
              id: 'code-assets.components.treeAndDiff.tree.NoFileChanges',
              defaultMessage: '没有文件改动',
            })}
            image="none"
          />
        </div>
      );
    }
  };

  onSelect = (selectedKeys) => {
    const elementKey = sha1(selectedKeys[0]);
    const element = document.getElementById(`anchor_file_${elementKey}`);
    const elementParent = document.getElementsByClassName('commit-right-content-list')[0];
    if (element && elementParent) {
      const elementOffsetTop = element.offsetTop;
      elementParent.scrollTop = elementOffsetTop;
    }
  };

  render() {
    // isNewCommitOnchange 表示新版提交详情
    const { diffs, loading, isNewCommitOnchange } = this.props;
    const { searchText } = this.state;

    const filteredDiffs = diffs.filter(
      (diff) => diff.new_path.toLowerCase().indexOf(searchText.toLowerCase()) !== -1,
    );

    // 新版提交详情文件树处理（就是树形样式的变化，个人认为老版更好用）
    // newTreeFromPaths(
    //   filteredDiffs.map((item) => item.new_path),
    //   '',
    //   (parent, file, explicit) => ({
    //     path: `${parent}${file}`,
    //     name: `${file}`,
    //     isFile: explicit,
    //   }),
    //   {},
    //   diffs,
    // );

    const treeData = treeFromPaths(
      filteredDiffs.map((item) => item.new_path),
      '',
      (parent, file, explicit) => ({
        path: `${parent}${file}`,
        name: `${file}`,
        isFile: explicit,
      }),
    );

    const recursiveFuncNode = (node) => {
      if (
        node.label &&
        !node.label.isFile &&
        node.nodes.length === 1 &&
        !node.nodes[0].label.isFile
      ) {
        node.label = {
          path: node.nodes[0].label.path,
          name: node.label.name + node.nodes[0].label.name,
          isFile: node.nodes[0].label.isFile,
        };

        node.nodes = node.nodes[0].nodes;

        recursiveFuncNode(node);
      } else if (node.nodes.length) {
        node.nodes.forEach((item) => {
          recursiveFuncNode(item);
        });
      }
    };

    // && !isNewCommitOnchange
    if (treeData?.nodes?.length) {
      treeData.nodes.forEach((node) => {
        recursiveFuncNode(node);
      });
    }

    return (
      <div
        className={
          isNewCommitOnchange ? 'commit-new-change-tree' : 'commit-change-tree changes-tree'
        }
      >
        {this.renderTree(filteredDiffs, treeData, loading)}
      </div>
    );
  }
}
